#include "nr_channel_input.h"
#include "nr_channel_output.h"

nr_channel_input::nr_channel_input()
    : m_device_item(NULL)
{
}

nr_channel_input::~nr_channel_input()
{
    stop();
}

nr_error_t nr_channel_input::put_data(nr_data* data)
{
    // Emit data to each channel
    foreach(nr_channel_output* output, m_output_channels)
    {
        output->fire_data(data);
    }

    return NR_ERROR_NONE;
}

nr_error_t nr_channel_input::put_event(nr_event* evt)
{
    // Emit event to each channel
    foreach(nr_channel_output* output, m_output_channels)
    {
        output->fire_event(evt);
    }

    return NR_ERROR_NONE;
}

void nr_channel_input::attach_device_item(nr_device_item *item)
{
    Q_ASSERT(m_device_item == NULL && item != NULL);
    m_device_item = item;
}

nr_error_t nr_channel_input::add_output_channel(nr_channel_output *output_channel)
{
    Q_ASSERT(output_channel);
    Q_ASSERT(!m_output_channels.contains(output_channel->channel_id()));

    m_output_channels.insert(output_channel->channel_id(), output_channel);;
    return NR_ERROR_NONE;
}

nr_error_t nr_channel_input::remove_output_channel(nr_channel_output *output_channel)
{
    Q_ASSERT(output_channel);
    
    nr_output_channels::iterator it = m_output_channels.find(output_channel->channel_id());
    if (it != m_output_channels.end())
    {
        Q_ASSERT(it.value() == output_channel);
        m_output_channels.erase(it);    
        return NR_ERROR_NONE;
    }
    else
        return NR_ERROR_CHANNEL_NOT_FOUND;
}

void nr_channel_input::on_data_received(nr_data *data)
{
    put_data(data);
}

void nr_channel_input::on_event_report(nr_event *evt)
{
    put_event(evt);
}

nr_error_t nr_channel_input::on_starting(nr_channel_operation& operation)
{
    // Start the input channel, if it is not started
    if (m_state != NR_CHANNEL_STATE_STARTED)
    {
        return start();
    }

    return NR_ERROR_NONE;
}

nr_error_t nr_channel_input::on_started(nr_channel_operation& operation)
{
    return NR_ERROR_NONE;
}

nr_error_t nr_channel_input::on_pausing(nr_channel_operation& operation)
{
    return pause();
}

nr_error_t nr_channel_input::on_paused(nr_channel_operation& operation)
{
    return NR_ERROR_NONE;
}

nr_error_t nr_channel_input::on_stopping(nr_channel_operation& operation) 
{
    return NR_ERROR_NONE;
}

nr_error_t nr_channel_input::on_stopped(nr_channel_operation& operation)
{
    // Check if all the channels are paused
    bool need_stop = true;
    foreach(nr_channel_output* output_channel, m_output_channels)
    {
        if (output_channel->state() != NR_CHANNEL_STATE_STOPPED)
        {
            need_stop = false;
        }
    }
    
    // Stop it 
    if (need_stop)
    {
        return stop();
    }

    return NR_ERROR_NONE;
}

nr_error_t nr_channel_input::start()
{ 
    if (m_state == NR_CHANNEL_STATE_STARTED)
        return NR_ERROR_NONE;

    Q_ASSERT(m_device_item && m_device_item->device());

    m_device_item->device()->set_delegate(this);

    // Start the device to receive data and event
    nr_error_t status = m_device_item->device()->start();
    if (NR_SUCCEED(status))
    {
        m_state = NR_CHANNEL_STATE_STARTED;
    }

    return status; 
}

nr_error_t nr_channel_input::pause() 
{ 
    return NR_ERROR_NOT_SUPPORT; 
}

nr_error_t nr_channel_input::stop() 
{ 
    if (m_state == NR_CHANNEL_STATE_STOPPED)
        return NR_ERROR_NONE;

    Q_ASSERT(m_device_item && m_device_item->device());

    // Stop the device to stop receiving data and events
    nr_error_t status = m_device_item->device()->stop();
    if (NR_SUCCEED(status))
    {
        m_state = NR_CHANNEL_STATE_STOPPED;
    }

    return status;
}

